﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using Tilver.Common;

namespace Tilver.ExceptionHandling
{
    /// <summary>
    /// 异常信息分析类，分析产生异常原因和位置
    /// </summary>
    [Serializable]
    public class ExceptionData
    {
        #region Fields
        /// <summary>
        /// 获取引发异常的对象
        /// </summary>
        public Exception InnerException { get; set; }

        /// <summary>
        /// 获取引发异常的类型
        /// </summary>
        public string ExceptionType { get; set; }

        /// <summary>
        /// 获取引发异常的信息
        /// </summary>
        public string Message { get; set; }

        /// <summary>
        /// 获取引发异常的应用程序集名称
        /// </summary>
        public string AssemblyName { get; set; }

        /// <summary>
        /// 获取引发异常的类名
        /// </summary>
        public string ClassName { get; set; }

        /// <summary>
        /// 获取引发异常的方法名
        /// </summary>
        public string MethodName { get; set; }

        /// <summary>
        /// 获取引发异常的文件名
        /// </summary>
        public string FileName { get; set; }

        /// <summary>
        /// 获取引发异常的行号
        /// </summary>
        public int LineNumber { get; set; }

        /// <summary>
        /// 获取或设置引发异常的堆栈信息
        /// </summary>
        public List<ExceptionStackTraceData> StackTrace { get; set; }

        /// <summary>
        /// 获取或设置引发异常的用户自定义数据
        /// </summary>
        public SerializableDictionary<object, object> UserData { get; set; }
        #endregion

        #region Constructs
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="ex">要分析的异常</param>
        public ExceptionData(Exception ex)
        {
            InnerException = ex;
            ExceptionType = ex.GetType().ToString();
            Message = ex.Message;
            UserData = new SerializableDictionary<object,object>();
            if (ex.Data != null && ex.Data.Count > 0)
            {
                foreach (DictionaryEntry entry in ex.Data)
                {
                    UserData.Add(entry.Key, entry.Value);
                }
            }

            StackTrace = new List<ExceptionStackTraceData>();
            System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(ex, true);
            System.Diagnostics.StackFrame[] sfs = st.GetFrames();
            bool hasLast = false;
            for (int i = 0; i < sfs.Length; i++)
            {
                ExceptionStackTraceData data = GetStackTraceData(sfs[i]);
                if (!data.IsGlobalAssembly && !hasLast)
                {
                    AssemblyName = data.AssemblyName;
                    ClassName = data.ClassName;
                    MethodName = data.MethodName;
                    FileName = data.FileName;
                    LineNumber = data.LineNumber;
                    hasLast = true;
                }
                StackTrace.Add(data);
            }
        }

        private static ExceptionStackTraceData GetStackTraceData(System.Diagnostics.StackFrame sf)
        {
            ExceptionStackTraceData ret = new ExceptionStackTraceData();
            System.Reflection.MethodBase method = sf.GetMethod();
            ret.AssemblyName = method.Module.Name;
            ret.ClassName = method.ReflectedType.FullName;
            ret.MethodName = method.ToString();
            ret.FileName = sf.GetFileName();
            ret.LineNumber = sf.GetFileLineNumber();
            ret.IsGlobalAssembly = method.Module.Assembly.GlobalAssemblyCache;
            return ret;
        }
        #endregion

        #region Serialize(StackTrace,UserData)
        /// <summary>
        /// 获取堆栈字符串信息的反序列化对象
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static List<ExceptionStackTraceData> GetStackTrace(string str)
        {
            List<ExceptionStackTraceData> ret = null;
            if (string.IsNullOrEmpty(str))
            {
                ret = new List<ExceptionStackTraceData>();
            }
            else
            {
                ret = (List<ExceptionStackTraceData>)XmlSerializerHelper.Deserialize(typeof(List<ExceptionStackTraceData>), str);
            }
            return ret;
        }

        /// <summary>
        /// 获取堆栈信息的序列化字符串
        /// </summary>
        /// <returns></returns>
        public string GetStackTraceString()
        {
            string ret = string.Empty;
            if (StackTrace != null && StackTrace.Count > 0)
            {
                ret = XmlSerializerHelper.Serialize(typeof(List<ExceptionStackTraceData>), StackTrace);
            }
            return ret;
        }

        /// <summary>
        /// 获取用户数自定义据字符串的反序列化对象
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static SerializableDictionary<object, object> GetUserData(string str)
        {
            SerializableDictionary<object, object> ret = null;
            if (string.IsNullOrEmpty(str))
            {
                ret = new SerializableDictionary<object, object>();
            }
            else
            {
                ret = (SerializableDictionary<object, object>)XmlSerializerHelper.Deserialize(typeof(SerializableDictionary<object, object>), str);
            }
            return ret;
        }

        /// <summary>
        /// 获取用户自定义数据的序列化字符串
        /// </summary>
        /// <returns></returns>
        public string GetUserDataString()
        {
            string ret = string.Empty;
            if (UserData != null && UserData.Count > 0)
            {
                ret = XmlSerializerHelper.Serialize(typeof(SerializableDictionary<object, object>), UserData);
            }
            return ret;
        }
        #endregion
    }
}
